SASS 原先是 Ruby 這套程式語言,在設計樣式(CSS)時因撰寫習慣而衍生出來的語言,它具有使用「縮排語法」排版的語法結構,並提供了方便的巢狀結構,而得益於誕生之後的持續發展,直到現今他具備了變數、回圈、模組、函式等程式開發常見的概念,並一躍成了如今前端開發的主要工具之一。
使用巢狀結構使得我們的語法具有明確的階層性,可以更好的用 html 的思維進行開發設計。
nav
ul
margin: 0
padding: 0
list-style: none
li
display: inline-block
a
display: block
padding: 6px 12px
text-decoration: none
在編譯完之後再有階層的情況下,還會自動幫我們帶如選擇器的標籤結構
nav ul {
margin: 0;
padding: 0;
list-style: none;
}
nav li {
display: inline-block;
}
nav a {
display: block;
padding: 6px 12px;
text-decoration: none;
}
這邊說回來我們為何要使用 SASS,這邊可以套用他官方網站介紹自己的話語:原文:「Sass is the most mature, stable, and powerful professional grade CSS extension language in the world.」 翻譯:「Sass 是世界上最成熟、穩定、強大且專業級 CSS 擴展語言」
而擴充語法在這裡有一個很重要的概念,這裡可以簡單地說成他並未捨棄任何原有的 CSS 語法,而是以原先的 CSS 作為基底,在此基礎上新增屬於 SASS 可以使用的功能,因此即使在完全不操作 SASS 的情況下,也可以依照原先的開發習慣照常開發。
說回我們為什麼需要使用 SASS 來撰寫樣式,先不要管他對於自身的評價,我們可以去反思原先 CSS 有什麼問題,過多雷同的樣式撰寫,類似的命名規則需重複設定,專案規模大時色彩的不可控,尺寸與間距若沒預設規範尺寸時將永遠不可知等,傳統的樣式撰寫始終只是負責進行畫面的呈現,維護與可讀等很顯然不是他的考慮範圍,而在 SASS 的設計裡,這一些問題將會一次性的獲得解決,而這也是我們將要使用 SASS 的最佳誘因。
.main {
max-width: 1200px;
width: 80%;
margin: auto;
}
.list {
display: flex;
}
.main {
max-width: 1200px;
width: 80%;
margin: auto;
}
.list {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
}
這邊需要提及一個概念,為了讓 CSS 可以在各種瀏覽器正常運作,我們會需要在一些屬性或參數前新增前綴,雖然即使不加其實顯示也不一定會有問題,但保守一點總是比較好的,然而在實務上這點其實非常讓人困擾,因為這類型的樣式或屬性可說是數不勝數,一個一個撰寫更是一件暗無天日的考驗,而此時 SASS 這類型的擴充語言就像是聽見我們的哀嚎般,在後來的版本中將此納入了匯出的格式(可靠設定讓他不產出前綴),使得我們不用再自行新增這麼大量的額外標籤。
在實際專案當中,我們其實並不會推薦使用這個編譯器,原因是因為編譯版本的問題,以 SASS 目前最新版的語法來說,這個編譯器遺憾的並不支援,而在實務進入專案與架構的開發時,我們的開發環境也會自行幫我們使用最新版本進行編譯,因此並不需要採用此編譯器,但在初步探索 SASS 並學習的現在,這套依然會是我們的最佳首選。
因為實際要跑新版的編譯器,需操作電腦 node 與 npm 環境等,對大多數沒有學習過 JavaScript 或電腦指令的同學相當的不友善。
在我們安裝完成之後,理論上就可以直接啟動編譯,但要記住我們不是魔法師,無法無中生有的讓他編譯出東西,因此在初次的操作中,請同學在專案的任何一個地方建立一個 style.scss 的檔案,內容可以先不放置,然後在點擊下方 Watch Sass 的按鈕開始編譯。
:::warning
注意:請記得開啟一個資料夾
:::
.main {
max-width: 1200px;
width: 80%;
margin: auto;
}
.list {
display: flex;
}
此時不出意外的話,style.css 與 style.css.map 的檔案將會自動被建置出來,.map 的檔案是協助我們的開發者工具確認 css 與 scss 之間的結構的,並記錄操作位子的檔案,通常並不需要去在意。
細心的同學應該會發現,我們此時用的副檔名並不是使用 .sass 而是使用 .scss,這是為了因應過往 CSS 開發者的操作習慣,縮排語法並畢竟與原生的語法有著過大的落差,因此 SASS 官方提供了一套更貼近於 CSS 的語法,使我們可以在操作過往 CSS 的習慣下,繼續使用 SASS 所提供的功能。
$color_accent: #1f1b7d;
$color_text-color: #13122d;
body {
background-color: $color_accent;
color: $color_text-color;
}
h1 {
color: $color_accent;
}
body {
background-color: #1f1b7d;
color: #13122d;
}
h1 {
color: #1f1b7d;
}
在撰寫 SCSS 的使用,我們可以藉由一個關鍵字「&」,去取得目前所在選擇器的寫法,他可以很輕鬆的讓我們指定自身的偽元素或偽選擇器,並且在 BEM 語法規章的撰寫中,也讓我們可以更優雅的撰寫我們的樣式。
body {
.container {
max-width: 1200px;
width: 80%;
}
}
.box {
width: 80px;
.box__title {
font-size: 1.5em;
}
&__text {
font-size: 1.1em;
}
}
body .container {
max-width: 1200px;
width: 80%;
}
.box {
width: 80px;
}
.box .box__title {
font-size: 1.5em;
}
.box__text {
font-size: 1.1em;
}
"liveSassCompile.settings.formats": [
{
"extensionName": ".css",
"format": "expanded",
"savePath": "/assets/css"
}
],
如同顏色定義的檔案與一些參數設定等等,這些很明顯是不需要進入我們最終產出的結果,因此我們可以把檔案名稱前面加上「 _ 」這個下底線,編譯器再看到這個前綴時會自動不對他進行編譯。
// _color.scss
$color_accent: #1f1b7d;
$color_text-color: #13122d;
// style.scss
@import 'color';
body {
background-color: $color_accent;
color: $color_text-color;
}
h1 {
color: $color_accent;
}
官網的範例使用的是 @use ,但因為我們所使用的編譯器的版本問題,因此無法進行這此操作。
body {
background-color: #1f1b7d;
color: #13122d;
}
h1 {
color: #1f1b7d;
}
在撰寫樣式時,我們很常需要對「同樣」類型的 UI 進行重複的操作,而這很顯然並不符合效率這一詞,而混合(Mixin)的操作,可以協助我們進行這類型重複的撰寫,並且讓我們可以藉由自主設定變數的方式,快速製造出各類不同的樣式,並且我們甚至可以在變數後方增添預設參數,並藉由關鍵字 @include 進行操作。
@mixin btnHover($backgroundColor, $hoverColor: #1e1e6f) {
padding: 10px 20px;
background-color: $backgroundColor;
color: white;
transition: background-color 300ms;
&:hover {
background-color: $hoverColor;
// background-color: darken($color: $backgroundColor, $amount: 20);
}
}
.blue-btn {
@include btnHover(blue);
}
.red-btn {
@include btnHover(red, rgb(114, 28, 28));
}
在上方範例的註解中,我們用了 SASS 提供的一個色彩函式,使我們可以透過計算飽和度或明亮度等方式產生色彩,這使我們在設計與操作上擁有了更加龐大的彈性。
相關文件檔案
.blue-btn {
padding: 10px 20px;
background-color: blue;
color: white;
-webkit-transition: background-color 300ms;
transition: background-color 300ms;
}
.blue-btn:hover {
background-color: #1e1e6f;
}
.red-btn {
padding: 10px 20px;
background-color: red;
color: white;
-webkit-transition: background-color 300ms;
transition: background-color 300ms;
}
.red-btn:hover {
background-color: #721c1c;
}
/*# sourceMappingURL=style.css.map */
在繼承與延展的操作中,我們可以藉由 @extend 的方式,來將我們目前的區塊進行繼承的操作,概念上就是讓目前的區塊,可以去繼承其他的樣式所撰寫的內容,其中也包含了複雜的階層結構,而另外 SASS 也有提供一個 「佔用類別(placeholder classes)」,他可以允許我們先行定義一個區塊並進行撰寫,隨後在由其他的樣式進行繼承。
%flex-center {
display: flex;
align-items: center;
justify-content: center;
}
body {
min-height: 100vh;
@extend %flex-center;
}
.header {
@extend body;
}
.navbar {
@extend %flex-center;
}
body, .header, .navbar {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
}
body, .header {
min-height: 100vh;
}
以下方的範例為例,我們甚至連複雜的階層結構都可以進行繼承,這使得我們在相同 UI 的撰寫上,可以更加方便地進行操作。
ul {
display: block;
li {
display: inline-block;
}
}
.work {
@extend ul;
}
ul, .work {
display: block;
}
ul li, .work li {
display: inline-block;
}
其實 SCSS 的進階操作有非常多的討論空間,但因為我們是初步進行學習,因此這邊就先只對常用的「流程控制規則(Flow Control)」進行探討。
布林的判斷其實是我們日常生活的常態,同時他也是計算機語言的根基之一,但說起來其實並不複雜,他就是單純的 Yes or No 而已。
@mixin avatar($size, $circle: false) {
width: $size;
height: $size;
@if $circle {
border-radius: $size / 2;
} @else {
border-radius: 10px;
}
}
.square-avatar {
@include avatar(100px, $circle: false);
}
.circle-avatar {
@include avatar(100px, $circle: true);
}
.square-avatar {
width: 100px;
height: 100px;
border-radius: 10px;
}
.circle-avatar {
width: 100px;
height: 100px;
border-radius: 50px;
}
each 的作用是會對一個實體進行遍歷,基本上就是一個不漏的全部進行一次操作,當我們對於區塊有明確的需求或定義時,他將是我們堅定的朋友。
$sizes: 40px, 50px, 80px;
@each $size in $sizes {
.icon-#{$size} {
font-size: $size;
height: $size;
width: $size;
}
}
.icon-40px {
font-size: 40px;
height: 40px;
width: 40px;
}
.icon-50px {
font-size: 50px;
height: 50px;
width: 50px;
}
.icon-80px {
font-size: 80px;
height: 80px;
width: 80px;
}
$titles: (
'h1': 2rem,
'h2': 1.75rem,
'h3': 1.5rem,
);
@each $name, $size in $titles {
#{$name} {
color: rgb(74, 61, 104);
font-size: $size;
}
}
h1 {
color: #4a3d68;
font-size: 2rem;
}
h2 {
color: #4a3d68;
font-size: 1.75rem;
}
h3 {
color: #4a3d68;
font-size: 1.5rem;
}
for 迴圈是在任何程式語言中的老朋友,我們可以藉由他去跑一個累計的迴圈操作,理論上當我們遇到重複性質高的工作時,for 就會來幫我們解決這個問題。
@for $i from 1 through 3 {
.col-#{$i} {
flex: $i;
}
}
.col-1 {
-webkit-box-flex: 1;
-ms-flex: 1;
flex: 1;
}
.col-2 {
-webkit-box-flex: 2;
-ms-flex: 2;
flex: 2;
}
.col-3 {
-webkit-box-flex: 3;
-ms-flex: 3;
flex: 3;
}
其實最後還有一個 @while 操作,但因為這會牽扯到 @function 等函式應用,因此在基礎課程先不進行談論。